# -*- coding: utf-8 -*-
# nlp-api.py
# Created by Hardy on 15th, Jan
# Copyright 2017 杭州网川教育有限公司. All rights reserved.

from flask import Flask, jsonify
from flask_restful import Resource, Api, reqparse
import logging
import logging.config
import sys
import yaml
from nlp import NLPService


NLP_SERVICE = 'nlp_service'
USER_DICT = 'user_dict'
MODEL_PATH = 'model_path'
WORD2VEC = 'word2vec'
CLASSIFIER = 'classifier'
DV_MODEL_PATH = 'dv_model_path'
LG_MODEL_PATH = 'lg_model_path'
TFIDF_MODEL_PATH = 'tfidf_model_path'
KEYWORD_METHOD = 'keyword_method'
STOPWORDS_FILE = 'stopwords_file'
APP_SERVE = 'app_serve'

ARG_TEXT = 'text'
ARG_TOP_K = 'keyword_top_k'
ARG_TOP_N = 'keyword_cloud_n'
ARG_ALLOW_POS = 'keyword_allow_pos'
ARG_TF = 'keyword_tf'
ARG_KEYWORDS = 'keywords'
ARG_DICT = 'arg_dict'


def load_yaml(yaml_file):
    with open(yaml_file, 'r') as infile:
        config = yaml.load(infile)
    return config


def set_logging(conf_file):
    config = load_yaml(conf_file)
    logging.config.dictConfig(config)


class NLPResource(Resource):
    nlp_service = None

    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument(ARG_TEXT, type=str, location='json')
        self.parser.add_argument(ARG_DICT, type=dict, location='json')
        self.parser.add_argument(ARG_TOP_K, type=int, location='json')
        self.parser.add_argument(ARG_TOP_N, type=int, location='json')
        self.parser.add_argument(ARG_ALLOW_POS, type=list, location='json')
        self.parser.add_argument(ARG_KEYWORDS, type=list, location='json')
        self.logger = logging.getLogger()
        # self.parser.add_argument(ARG_TF, type=bool, location='json')

    @classmethod
    def setResource(cls, nlp_service=None):
        cls.nlp_service = nlp_service

    def get(self):
        args = self.parser.parse_args()
        self.logger.debug('args: %s' % str(args))
        try:
            res = self._process(args)
            return jsonify({'result': res})
        except Exception as ex:
            return jsonify({'message': 'Error %s' % str(ex)})

    def post(self):
        args = self.parser.parse_args()
        self.logger.debug('args: %s' % str(args))
        try:
            res = self._process(args)
            return jsonify({'result': res})
        except Exception as ex:
            return jsonify({'message': 'Error %s' % str(ex)})

    def _process(self, args):
        raise NotImplementedError()


class KeywordCloudResource(NLPResource):
    def _process(self, args):
        text = args[ARG_TEXT]
        keyword_top_k = args[ARG_TOP_K]
        top_n = args[ARG_TOP_N]
        keyword_allow_pos = args[ARG_ALLOW_POS]
        # keyword_tf = args[ARG_TF]
        keywords = self.__class__.nlp_service.get_keywords(text, keyword_top_k, keyword_allow_pos)
        return self.__class__.nlp_service.get_similar_words(keywords, topn=top_n)


class ClassifierResource(NLPResource):
    def _process(self, args):
        keywords = args[ARG_KEYWORDS]
        self.logger.debug(self.__class__.nlp_service)
        return self.__class__.nlp_service.classify(keywords)


class GetWordVectors(NLPResource):
    def _process(self, args):
        arg_dict = args[ARG_DICT]
        if not arg_dict:
            arg_dict = dict()
        texts = arg_dict.get('texts', [])
        self.logger.debug(self.__class__.nlp_service)
        return self.__class__.nlp_service.get_word_vectors(texts)


class WordCloudResource(NLPResource):
    def _process(self, args):
        keywords = args[ARG_KEYWORDS]
        top_n = args[ARG_TOP_N]
        self.logger.debug(self.__class__.nlp_service)
        return self.__class__.nlp_service.get_similar_words(keywords, topn=top_n)


class KeywordResource(NLPResource):
    def _process(self, args):
        text = args[ARG_TEXT]
        keyword_top_k = args[ARG_TOP_K]
        keyword_allow_pos = args[ARG_ALLOW_POS]
        # keyword_tf = args[ARG_TF]
        return self.__class__.nlp_service.get_keywords(text, keyword_top_k, keyword_allow_pos)


class SegResource(NLPResource):
    def _process(self, args):
        text = args[ARG_TEXT]
        return self.__class__.nlp_service.get_seg(text)


def load_nlp_app(config_file, logging_config_file):
    set_logging(logging_config_file)

    config = load_yaml(config_file)[NLP_SERVICE]

    model_path = config[WORD2VEC][MODEL_PATH]
    keyword_method = config[WORD2VEC][KEYWORD_METHOD]
    user_dict = config[WORD2VEC][USER_DICT]

    dv_model_path = config[CLASSIFIER][DV_MODEL_PATH]
    lg_model_path = config[CLASSIFIER][LG_MODEL_PATH]
    tfidf_model_path = config[CLASSIFIER][TFIDF_MODEL_PATH]
    stopwords_file = config[STOPWORDS_FILE]

    nlp_service = NLPService(model_path, user_dict, stopwords_file, keyword_method, dv_model_path, lg_model_path, tfidf_model_path)

    # app_serve = config[APP_SERVE]

    NLPResource.setResource(nlp_service)

    app = Flask(__name__)
    # app.config['SECRET_KEY'] = 'you are a fool'
    api = Api(app)

    # logger = logging.getLogger()
    # logger.debug(nlp_service.get_seg("我是中国人"))
    api.add_resource(KeywordCloudResource, '/keywordcloud')
    api.add_resource(WordCloudResource, '/wordcloud')
    api.add_resource(KeywordResource, '/keyword')
    api.add_resource(SegResource, '/seg')
    api.add_resource(ClassifierResource, '/classify')
    api.add_resource(GetWordVectors, '/word_vectors')

    return app


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print('Usage: python3.4 start_api.py <config.yaml> <logging.yaml>')
        exit(1)
    config_file = sys.argv[1]
    logging_config_file = sys.argv[2]

    config = load_yaml(config_file)[NLP_SERVICE]

    app = load_nlp_app(config_file, logging_config_file)
    app.run(**config[APP_SERVE])

